package com.chenyue.cm.utils;

import com.chenyue.cm.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class RedisLock {
    private static Logger logger = LoggerFactory.getLogger(RedisLock.class);

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 加锁
     * @param key
     * @param value 当前时间+超时时间
     * @return
     */
    public boolean lock(String key,String value){
        //加锁成功(reids的setIfAbsent方法表示:在某个时刻缓存中是否存在键值,存在则不改变已有的值,不存在则新增)
        if (redisTemplate.opsForValue().setIfAbsent(key,value)){
            return true;
        }
        //假如currentValue=A先占用了锁  其他两个线程的value都是B,保证其中一个线程拿到锁
        String currentValue = redisTemplate.opsForValue().get(key);
        //锁过期  防止出现死锁
        if (!StringUtils.isEmpty(currentValue) &&
                Long.parseLong(currentValue) < System.currentTimeMillis()){
            //获取上一步锁的时间
            String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
            if (!StringUtils.isEmpty(oldValue) &&
                    oldValue.equals(currentValue)){
                return true;
            }
        }
        return false;
    }

    /**
     * 解锁
     * @param key
     * @param value
     */
    public void unlock(String key,String value){
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (!StringUtils.isEmpty(currentValue) &&
                    currentValue.equals(value)){
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }catch (Exception e){
            logger.error("【redis分布式锁】 解锁异常，{}",e);
        }
    }


//    public boolean lock(long timeout,int expire){
//        long nanoTime = System.nanoTime();
//        timeout *= MILLI_NANO_TIME;
//        try {
//            //在timeout的时间范围内不断轮询锁
//            while (System.nanoTime() - nanoTime < timeout) {
//                //锁不存在的话，设置锁并设置锁过期时间，即加锁
//                if (this.redisClient.setnx(this.key, LOCKED) == 1) {
//                    this.redisClient.expire(key, expire);//设置锁过期时间是为了在没有释放
//                    //锁的情况下锁过期后消失，不会造成永久阻塞
//                    this.lock = true;
//                    return this.lock;
//                }
//                System.out.println("出现锁等待");
//                //短暂休眠，避免可能的活锁
//                Thread.sleep(3, RANDOM.nextInt(30));
//            }
//        } catch (Exception e) {
//            throw new RuntimeException("locking error",e);
//        }
//        return false;
//    }
//    public  void unlock() {
//        try {
//            if(this.lock){
//                redisClient.delKey(key);//直接删除
//            }
//        } catch (Throwable e) {
//        }
//    }

}
